<?php
// load internationalization in the very start of the Appliation
require_once 'Kernel/i18n.php';


/**
 * Класс приложения. Надо потом сформулировать, что же он делает.
 * :TODO: morozov 17052007: по идее это же и есть цепочка фильтров, тока режим
 * отладки здесь не пришей кобыле хвост. Надо убрать его отсюда (в конфиг модуля
 * ядра, например) и переобозвать класс.
 *
 */
abstract class Kernel_Application 
{

    /**
     * @desc Dummy? 
     *
     * @var
     */
    static private $_dummy;

    /**
     * @desc Application request object. 
     *
     * @var Kernel_Request_Interface
     */
    static private $_request;

    /**
     * @desc Application response object. 
     *
     * @var Kernel_Response_Abstract
     */
    static private $_response;

    /**
     * @desc Application start mode. 
     *
     * @var Kernel_Mode_Abstract
     */
    static private $_mode;

    /**
     * @desc Start specified filters' list and handle response. 
     *
     * @param   Dummy   $dummy
     * @param   array   $filters
     */
    static public function run($dummy, $filters) 
    {

        if (!self::isDebugMode()) {
            set_error_handler(array(new Kernel_ErrorCatcher, 'process'));
        }

        self::$_dummy = $dummy;
        self::$_mode = $mode = Kernel_Mode_Factory::get();
        self::$_request = $mode->getRequest();
        self::$_response = $mode->getResponse();
        self::chain($filters);

        self::$_response->close();
    }

    /**
     * @desc Return dummy. 
     *
     * @return  boolean
     */
    static public function dummy() 
    {
        return self::$_dummy;
    }

    /**
     * @desc Return whether apllication uses debug mode. 
     *
     * @return  boolean
     */
    static public function isDebugMode() 
    {
        return defined('DEBUG_MODE') && constant('DEBUG_MODE');
    }

    /**
     * @desc Return request object. 
     *
     * @return  Kernel_Request_Interface
     */
    static public function getRequest() 
    {
        return self::$_request;
    }

    /**
     * @desc Return application start mode object. 
     *
     * @return  Kernel_Mode_Abstract
     */
    static public function getMode() 
    {
        return self::$_mode;
    }

    /**
     * @desc Return response object. At one set response type if it's defined. 
     *
     * @param   string  $type
     * @return  Kernel_Response_Abstract
     */
    static public function getResponse($type = null) 
    {
        if (func_num_args() > 0) {
            self::setResponse($type);
        }
        return self::$_response;
    }

    /**
     * @desc Set response type. 
     *
     * :TODO: morozov 27032008: сделать возможность менять тип ответа, сохраняя
     * при этом ранее переданные в ответ данные.
     *
     * @param   string  $type
     */
    static public function setResponse($type) 
    {
        self::$_response = Kernel::factory('Kernel_Response', $type);
    }

    /**
     * @desc Return path to the temporary directory. 
     *
     * @return  string
     */
    static public function getTmpDir() 
    {
        static $TMPDIR;
        if (!isset($TMPDIR)) {
            switch (true) {
                // пытаемся определить по переменным окружения
                case $TMPDIR = getenv('WIN' == substr(PHP_OS, 0, 3) ? 'TMP': 'TMPDIR');
                    break;
                // пытаемся определить по настройкам PHP (встречается у некоторых хостеров)
                case $TMPDIR = ini_get('upload_tmp_dir');
                    break;
                // если дойдет досюда, придется создать временную папку руками
                default:
                    $TMPDIR = SITE_ROOT . DIRECTORY_SEPARATOR . '_tmp';
                    break;
            }
        }
        return $TMPDIR;
    }

    /**
     * @desc Start specified filters' chain. 
     *
     * @param   array $filters
     */
    static public function chain($filters) 
    {
        try {
            while ($class = array_shift($filters)) {
                $re = new ReflectionClass($class);
                if ($re->isSubclassOf('Kernel_Wrapper')) {
                    $wrapper = new $class($filters);
                    $wrapper->run();
                    break;
                } else {
                    $filter = new $class;
                    $filter->process();
                }
            }
        } catch (Kernel_Filter_Exception $e) {
            self::getResponse()->error($e);
        }
    }
    
}

/**
 * @desc To avoid unnecessary letters in code. 
 *
 */
class Application extends Kernel_Application { }